package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.tanhua.common.utils.UserThreadLocal;
import com.tanhua.dubbo.api.TestSoulApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.enums.QuestionCoverType;
import com.tanhua.dubbo.enums.QuestionLevel;
import com.tanhua.dubbo.enums.QuestionType;
import com.tanhua.dubbo.pojo.Report;
import com.tanhua.dubbo.pojo.SimpleReport;
import com.tanhua.dubbo.pojo.SoulQuestions;
import com.tanhua.dubbo.pojo.UserInfo;
import com.tanhua.dubbo.vo.TestSoulVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class TestSoulService {

    @DubboReference(version = "1.0.0")
    private TestSoulApi testSoulApi;

    @DubboReference(version = "1.0.0")
    private UserInfoApi userInfoApi;

    /**
     * 查询测灵魂问卷列表
     * @return
     */
    public List<TestSoulVo> questionList() {
        //创建结果集
        List<TestSoulVo> testSoulVoList = new ArrayList<>();

        Long userId = UserThreadLocal.get();
        //查询用户答题状态
        Integer[] statusArr = this.testSoulApi.queryUserSoulTestStatus(userId);//初始为[0,1,1]

        //封装每套问卷的结果
        TestSoulVo testSoulVo1 = this.setTestSoulVo(QuestionType.JUNIOR, QuestionCoverType.JUNIOR, QuestionLevel.JUNIOR, userId, statusArr[0]);
        TestSoulVo testSoulVo2 = this.setTestSoulVo(QuestionType.MIDDLE, QuestionCoverType.MIDDLE, QuestionLevel.MIDDLE, userId, statusArr[1]);
        TestSoulVo testSoulVo3 = this.setTestSoulVo(QuestionType.SENIOR, QuestionCoverType.SENIOR, QuestionLevel.SENIOR, userId, statusArr[2]);

        //添加到结果集中
        Collections.addAll(testSoulVoList,testSoulVo1,testSoulVo2,testSoulVo3);
        return testSoulVoList;
    }

    /**
     * 封装结果集
     * @param questionType
     * @param questionCoverType
     * @param questionLevel
     * @param userId
     * @param status
     * @return
     */
    private TestSoulVo setTestSoulVo(QuestionType questionType,QuestionCoverType questionCoverType, QuestionLevel questionLevel, Long userId, int status) {

        //查询问卷
        List<SoulQuestions> soulQuestions = this.testSoulApi.querySoulQuestions(questionLevel.getValue());
        //获取最新报告id
        SimpleReport simpleReport = this.testSoulApi.querySimpleReport(userId, questionLevel.getValue());
        String reportId = null;//无报告
        if (null != simpleReport) {
            reportId = simpleReport.getReportId();//有报告
        }
        //封装
        TestSoulVo testSoulVo = new TestSoulVo();
        testSoulVo.setQuestions(soulQuestions);//试题
        testSoulVo.setName(questionType.toString());//问卷名称
        testSoulVo.setCover(questionCoverType.toString());//封面
        testSoulVo.setLevel(questionLevel.toString());//级别
        testSoulVo.setStar(questionLevel.getValue());//星级
        testSoulVo.setIsLock(status);//是否锁住
        testSoulVo.setReportId(reportId);//最新报告id
        return testSoulVo;
    }

    /**
     * 提交问卷
     * @param param 答案
     * @return 报告id
     */
    public String submitQuestionList(Map<String,List<Map<String,String>>> param) {

        Long userId = UserThreadLocal.get();

        List<Map<String, String>> answers = param.get("answers");
        List<String> optionIds = new ArrayList<>();
        answers.forEach(stringStringMap -> {
            //获取答案计算总分
            String optionId = stringStringMap.get("optionId");//获取每道题的答案
            optionIds.add(optionId);//添加到集合中
        });

        //根据分数查询对应的报告id
        String reportId = this.totalScore(optionIds);


        //判断用户答题等级
        //先查询用户的答题状态
        Integer[] status = this.testSoulApi.queryUserSoulTestStatus(userId);
        String questionId = answers.get(0).get("questionId");//获取试卷第一题的题号
        if (StrUtil.equals(questionId, "1")) {//说明答的是初级，把中级解锁
            status[1] = 0;//修改状态数组
            //同时将简单信息存到 report-user关系表中(有修改，没有插入)
            this.testSoulApi.upsertSimpleReport(userId,reportId,QuestionLevel.JUNIOR.getValue());
        } else if (StrUtil.equals(questionId, "11")) {//说明答的是中级，把高级解锁
            status[2] = 0;
            //同时将简单信息存到 report-user关系表中(有修改，没有插入)
            this.testSoulApi.upsertSimpleReport(userId,reportId,QuestionLevel.MIDDLE.getValue());
        } else {
            //说明答的是高级
            //同时将简单信息存到 report-user关系表中(有修改，没有插入)
            this.testSoulApi.upsertSimpleReport(userId,reportId,QuestionLevel.SENIOR.getValue());
        }
        this.testSoulApi.updateUserSoulTestStatus(userId,status);//将修改的用户答题状态更新到数据库

        return reportId;
    }

    /**
     * 查询报告
     * @param reportId 报告id
     * @return
     */
    public Report queryReport(String reportId) {
        Long userId = UserThreadLocal.get();

        //查询报告
        Report report = this.testSoulApi.queryReportByReportId(reportId);
        //删掉similarYou中的自己(直接删除会产生并发修改异常，所以用迭代器删除)
        List<Map<Object, Object>> similarYou = report.getSimilarYou();
        Iterator<Map<Object, Object>> iterator = similarYou.iterator();
        while (iterator.hasNext()) {
            Map<Object, Object> next = iterator.next();
            if (userId.equals(Convert.toLong(next.get("id")))) {
                iterator.remove();
            }
        }

        //查询用户头像
        UserInfo userInfo = this.userInfoApi.queryByUserId(userId);

        //更新数据库中的报告中的”和我相似“字段
        this.testSoulApi.updateReportInSimilarYou(reportId, userId, userInfo.getLogo());

        return report;
    }

    /**
     * 计算总分,返回报告id
     * @param optionIds
     * @return
     */
    private String totalScore(List<String> optionIds) {
        if (CollUtil.isNotEmpty(optionIds)) {
            int total = 0;
            for (String optionId : optionIds) {
                switch (optionId) {
                    case "A" :
                        total += 4;
                        break;
                    case "B" :
                        total += 3;
                        break;
                    case "C" :
                        total += 2;
                        break;
                    case "D" :
                        total += 1;
                        break;
                    default:
                        total += 0;
                }
            }

            if (total >= 30 && total <= 40) {
                return "1";
            } else if (total >= 20 && total < 30) {
                return "2";
            } else if (total >= 10 && total < 20) {
                return "3";
            } else {
                return "0";
            }
        }
        return "0";
    }
}
